/**
 * 根据sqlite内容下载文件，下载成功后会修改 isDownload 标记，如果进程异常中止，可再次启动，已下载文件不会重复下载。
 * 可修改 POOL_SIZE 参数，表示同步执行的下载队列数
 */
const cheerio = require('cheerio');
const request = require('request')
const fs = require('fs')
const process = require('process')

const { db, updateMaven } = require('./db-helper');
const { httpGet } = require('./http-util');
const { log } = require('./util')
const { POOL_SIZE, TIMEOUT, MAVEN_REPO_URL, NEXUS_URL } = require('./config')

const QUERY_SQL = "select * from maven where id % ? = ? and (isDownload != '1' or isDownload is null)"

/**
 * 异步下载队列，将数据库中的任务按队列序号分配
 * @param seq 队列序号
 */
async function downloadMaven(seq) {
    let list = db.query(QUERY_SQL, POOL_SIZE, seq)
    let size = list ? list.length : 0;
    let failCount = 0;
    log.info(`创建下载队列:${seq}, 任务数：${size}`)
    for (let i = 0; i < size; i++) {
        let maven = list[i]
        let url = `${MAVEN_REPO_URL}${maven.groupId.replace(/\./g, '/')}/${maven.artifactId}/${maven.version}/`

        let begin = new Date().getTime()
        try {
            await getFiles(url)

            maven.isDownload = '1'
            maven.useTime = new Date().getTime() - begin
            updateMaven(maven)
            log.info(`队列${seq},下载库文件成功(${i + 1}/${size})：id=${maven.id}, groupId=${maven.groupId}, artifactId=${maven.artifactId}, version=${maven.version}`)
        } catch (e) {
            log.error(`队列${seq},下载库文件失败(${i + 1}/${size})：url=${url}, error=${e}`)
            failCount++
        }
    }
    log.info(`队列${seq} 完成, 任务数：${size}，失败：${failCount}`)
}

/**
 * 获取待下载的文件列表
 * @param {*} url 
 */
async function getFiles(url) {
    let res = await httpGet(url)
    let $ = cheerio.load(res)

    let dirs = []
    let files = []
    $('pre a').each((i, elem) => {
        let $a = $(elem)
        if ($a.html().endsWith('.jar') || $a.html().endsWith('.pom')) {
            files.push(url + $a.html())
        }
        if ($a.attr('href') != '../' && $a.attr('href').endsWith('/')) {
            dirs.push(url + $a.attr('href'))
        }
    })

    // 遍历目录
    for (let i in dirs) {
        await getFiles(dirs[i])
    }

    // 下载文件
    for (let i in files) {
        await downloadFile(files[i])
    }
}

/**
 * 下载单个文件，从本地仓库下载，并在完成后删除，nexus会缓存下载过的文件
 * @param {*} url 
 */
function downloadFile(url) {
    let filename = 'temp/' + url.split('/').pop();

    return new Promise((resolve, rejects) => {
        request({
            url: url.replace(MAVEN_REPO_URL, NEXUS_URL),
            timeout: TIMEOUT
        })
            .on('error', () => fs.rm(filename, rejects))
            // .on('error', rejects)
            .pipe(fs.createWriteStream(filename))
            .on('finish', () => fs.rm(filename, resolve))
        // .on('finish', resolve)

    })
}

module.exports = {
    getFiles, downloadFile
}

// 创建临时目录
fs.mkdir('temp', () => { })

//带 -df 参数时才执行
const args = process.argv.slice(2)
if (args && args.length && args[0] == '-df') {
    //开始下载任务
    for (let i = 0; i < POOL_SIZE; i++) {
        downloadMaven(i)
    }
}